package com.mingqijia.gassafety.webserver.service.workorder.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gap.basic.base.CommonResponse;
import com.gap.basic.exception.BizException;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.mingqijia.gassafety.db.entity.*;
import com.mingqijia.gassafety.db.entity.redis.LatestLog;
import com.mingqijia.gassafety.db.entity.vo.HistoryAlarmVo;
import com.mingqijia.gassafety.db.mapper.HistoryAlarmMapper;
import com.mingqijia.gassafety.db.mapper.HistoryBrokenMapper;
import com.mingqijia.gassafety.shared.constant.AsstConstants;
import com.mingqijia.gassafety.shared.utils.ApplicationUtils;
import com.mingqijia.gassafety.shared.utils.HeaderUtil;
import com.mingqijia.gassafety.shared.utils.HttpUtil;
import com.mingqijia.gassafety.shared.utils.commonUtils.PageUtil;
import com.mingqijia.gassafety.shared.utils.commonUtils.SnowflakeUtil;
import com.mingqijia.gassafety.webserver.request.workorder.asst.AsstOrderCreateRequest;
import com.mingqijia.gassafety.webserver.request.workorder.asst.OrderDeviceRequest;
import com.mingqijia.gassafety.webserver.request.workorder.asst.OrgInfoRequest;
import com.mingqijia.gassafety.webserver.request.workorder.asst.ScheduleDateRequest;
import com.mingqijia.gassafety.webserver.request.workorder.asst.WorkOrderCreateRequest;
import com.mingqijia.gassafety.shared.dto.OrderCancelDTO;
import com.mingqijia.gassafety.webserver.request.workorder.order.OrderCreateRequest;
import com.mingqijia.gassafety.webserver.response.workorder.asst.*;
import com.mingqijia.gassafety.webserver.service.*;
import com.mingqijia.gassafety.webserver.service.impl.EquipmentServiceImpl;
import com.mingqijia.gassafety.webserver.service.workorder.AsstWorkOrderService;
import com.mingqijia.gassafety.webserver.service.workorder.WorkOrderHistoryService;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 工单记录表 服务实现类
 * </p>
 *
 * @author guoliang.lao
 * @since 2022-09-15
 */
@Service
@Slf4j
public class AsstWorkOrderServiceImpl implements AsstWorkOrderService {

    @Autowired
    WorkOrderHistoryService workOrderHistoryService;
    @Autowired
    LatestLogService latestLogService;
    @Autowired
    EquipmentService equipmentService;
    @Autowired
    CompanyService companyService;
    @Value(value = "${asst.workOrder.doamin.url}")
    String workOrderUrl;
    @Value(value = "${asst.workOrder.lineBizCde}")
    String lineBizCde;
    @Autowired
    HttpUtil httpUtil;
    @Autowired
    HeaderUtil headerUtil;
    @Autowired
    EquipmentServiceImpl service;
    @Autowired
    OrganizationService organizationService;

    @Autowired
    private HistoryAlarmMapper historyAlarmMapper;

    @Autowired
    private HistoryBrokenMapper historyBrokenMapper;

    @Autowired
    ConsumerService consumerService;

    @Autowired
    DictionaryService dictionaryService;

    @Override
    public List<BizResponse> getBizList(String spId) {
        List resultList = new ArrayList<>();
        try {
            if (StringUtils.isEmpty(spId)) {
                spId = ApplicationUtils.getWorkingSpId();
            }
            String orgCode = companyService.getOrgCode(spId,null);

            String url = workOrderUrl + AsstConstants.BIZ_LIST_URL + orgCode;
            String body = httpUtil.getBody(null, url, null);
            log.info("时刻助手业务类型列表返回：" + body);
            JSONObject jsonObject = JSONObject.parseObject(body);
            CommonResponse<List<BizResponse>> res = JSONObject.toJavaObject(jsonObject, CommonResponse.class);
            if (res.getCode().equals(0)) {
                List<BizResponse> list = JSON.parseArray(jsonObject.getString("data"), BizResponse.class);
                for (BizResponse bizResponse : list) {
                    String[] lineBizCode = lineBizCde.split(",");
                    for (String s : lineBizCode) {
                        if (s.equals(bizResponse.getBizCode()) || s.equals(bizResponse.getPcode())) {
                            if (!bizResponse.getPcode().equals("0")) {
                                //5:报警器设备维修 6：报警器报警处理 7:智慧安防设备处理
                                if (bizResponse.getTemplateType().equals(5) || bizResponse.getTemplateType().equals(6)
                                        || bizResponse.getTemplateType().equals(7)) {
                                    log.info(bizResponse.toString());
                                    resultList.add(bizResponse);
                                }
                            } else {
                                log.info(bizResponse.toString());
                                resultList.add(bizResponse);
                            }
                        }
                    }
                }
            } else {
                log.error("时刻助手业务类型列表查询失败：{}", res.getMsg());
            }
        } catch (Exception e) {
            log.error("时刻助手业务类型列表查询异常", e);
        }
        log.info(resultList.toString());
        return resultList;
    }

    @Override
    public List<BizServeResponse> getServeList(String pcode,String spId) {
        try {
            if (StringUtils.isEmpty(spId)) {
                spId = ApplicationUtils.getWorkingSpId();
            }
            String orgCode = companyService.getOrgCode(spId,null);

            String url = workOrderUrl + AsstConstants.SERVE_LIST_URL + pcode + "/" + orgCode;
            String body = httpUtil.getBody(null, url, null);
            JSONObject jsonObject = JSONObject.parseObject(body);
            CommonResponse<List<BizServeResponse>> res = JSONObject.toJavaObject(jsonObject, CommonResponse.class);
            if (res.getCode().equals(0)) {
                return res.getData();
            } else {
                log.error("getServeList查询失败：{}", res.getMsg());
            }
        } catch (Exception e) {
            log.error("getServeList查询异常", e);
        }
        return new ArrayList<>();
    }

    @Override
    public List<SchedulingDateResponse> getOrderDate(ScheduleDateRequest params) {
        try {
            String spId = ApplicationUtils.getWorkingSpId();
            String orgCode = companyService.getOrgCode(spId,null);

            List<ScheduleDateRequest> list = new ArrayList<>();
            ScheduleDateRequest req = new ScheduleDateRequest();
            BeanUtils.copyProperties(params, req);
            req.setOrgCode(orgCode);
            list.add(req);

            String url = workOrderUrl + AsstConstants.GET_ORDER_DATE_URL;
            String body = httpUtil.getBody(JSONObject.toJSONString(list), url, null);
            JSONObject jsonObject = JSONObject.parseObject(body);
            CommonResponse<List<SchedulingDateResponse>> res = JSONObject.toJavaObject(jsonObject, CommonResponse.class);
            if (res.getCode().equals(0)) {
                return res.getData();
            } else {
                log.error("getOrderDate查询失败：{}", res.getMsg());
            }
        } catch (Exception e) {
            log.error("getOrderDate查询异常", e);
        }
        return new ArrayList<>();
    }

    @Override
    public PageUtil<HistoryListResponse> historyList(String imei, Integer page, Integer pageSize) {
        List<HistoryListResponse> resultList = new ArrayList<>();
        String spId = ApplicationUtils.getWorkingSpId();
        //所属组织
        List<String> spIds = organizationService.getSpIds(spId);
        List<Long> workIds = new ArrayList<>();
        LambdaQueryWrapper<HistoryAlarm> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(HistoryAlarm::getDeviceId, imei).eq(HistoryAlarm::getIsDeleted, 0)
                .in(HistoryAlarm::getSpId, spIds)
                .gt(HistoryAlarm::getWorkorderId, 0)
                .orderByDesc(HistoryAlarm::getCreatedAt);
        List<HistoryAlarm> historyAlarms = historyAlarmMapper.selectList(wrapper);
        if (!CollectionUtils.isEmpty(historyAlarms)) {
            workIds = historyAlarms.stream().map(HistoryAlarm::getWorkorderId).collect(Collectors.toList());
        }

        LambdaQueryWrapper<HistoryBroken> brokenLambdaQueryWrapper = new LambdaQueryWrapper<>();
        brokenLambdaQueryWrapper.eq(HistoryBroken::getDeviceId, imei).eq(HistoryBroken::getIsDeleted, 0)
                .in(HistoryBroken::getSpId, spIds)
                .gt(HistoryBroken::getWorkorderId, 0)
                .orderByDesc(HistoryBroken::getCreatedAt);
        List<HistoryBroken> historyBrokens = historyBrokenMapper.selectList(brokenLambdaQueryWrapper);
        if (!CollectionUtils.isEmpty(historyBrokens)) {
            List<Long> workIdList = historyBrokens.stream().map(HistoryBroken::getWorkorderId).collect(Collectors.toList());
            workIds.addAll(workIdList);
        }
        LambdaQueryWrapper<WorkOrderHistory> queryWrapper = new LambdaQueryWrapper<>();
        if (CollectionUtils.isEmpty(workIds)) {
            queryWrapper.eq(WorkOrderHistory::getDeviceId,imei);
        }else{
            List<Long> workOrderIds = workIds;
            queryWrapper.and(i->i.eq(WorkOrderHistory::getDeviceId,imei).or().in(WorkOrderHistory::getId, workOrderIds));
        }

        queryWrapper.eq(WorkOrderHistory::getIsDeleted, 0)
                .in(WorkOrderHistory::getSpId, spIds)
                .orderByDesc(WorkOrderHistory::getCreatedAt);

        Page<HistoryAlarmVo> pages = PageHelper.startPage(page, pageSize);
        List<WorkOrderHistory> list = workOrderHistoryService.list(queryWrapper);

        List<String> orderNos = list.stream().map(WorkOrderHistory::getOrderNo).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(orderNos)) {
            List<String> workOrderSpIds = dictionaryService.selectNewAsstSpMappingSpIds(spId);
            workOrderSpIds.addAll(spIds);
            List<AsstOrderListResponse> orderList = getOrderList(orderNos, null, workOrderSpIds);
            for (WorkOrderHistory history : list) {
                HistoryListResponse res = new HistoryListResponse();
                for (AsstOrderListResponse asstOrderListResponse : orderList) {
                    if (history.getOrderNo().equals(asstOrderListResponse.getOrderNo())) {
                        BeanUtils.copyProperties(asstOrderListResponse, res);
                        res.setSendTime(history.getCreatedAt());
                        res.setWorkSystemStr("时刻助手");
                        if (StringUtils.isEmpty(res.getOperatorBy())) {
                            res.setOperatorBy(history.getOperatorBy());
                        }
                        //时刻家发起的创建时间取工单创建时间
                        if (history.getWorkSystem().equals(AsstConstants.FROM_SYSTEM_1)) {
                            res.setCreateTime(asstOrderListResponse.getCreateTime());
                        } else {
                            //报警器发起的创建时间取history表的创建时间
                            res.setCreateTime(history.getCreatedAt());
                        }
                    }
                }
                resultList.add(res);
            }
        }
        PageUtil pageInfo = new PageUtil<>(page, pageSize, pages.getTotal(), resultList);
        return pageInfo;
    }

    @Override
    public PageUtil<WorkingOrderListResponse> workingOrderList(String imei, Integer page, Integer pageSize) {
        List<WorkingOrderListResponse> resultList = new ArrayList<>();
        String spId = ApplicationUtils.getWorkingSpId();
        //所属组织
        List<String> spIds = organizationService.getSpIds(spId);

        LambdaQueryWrapper<WorkOrderHistory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WorkOrderHistory::getDeviceId, imei).eq(WorkOrderHistory::getIsDeleted, 0)
                .in(WorkOrderHistory::getSpId, spIds).eq(WorkOrderHistory::getHandleStatus, 0)
                .orderByDesc(WorkOrderHistory::getCreatedAt);

        Page<HistoryAlarmVo> pages = PageHelper.startPage(page, pageSize);
        List<WorkOrderHistory> list = workOrderHistoryService.list(queryWrapper);

        List<String> orderNos = list.stream().map(WorkOrderHistory::getOrderNo).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(orderNos)) {
            List<AsstOrderListResponse> orderList = getOrderList(orderNos, null, spIds);
            for (WorkOrderHistory history : list) {
                WorkingOrderListResponse res = new WorkingOrderListResponse();
                for (AsstOrderListResponse asstOrderListResponse : orderList) {
                    if (history.getOrderNo().equals(asstOrderListResponse.getOrderNo())) {
                        BeanUtils.copyProperties(asstOrderListResponse, res);
                        res.setSendTime(history.getCreatedAt());
                        res.setEquipmentStatus(history.getDeviceStatus());
                        res.setReason(history.getReason());
                        if (history.getConcentration() != null) {
                            res.setXlel(history.getConcentration() + " %LEL");
                        } else {
                            res.setXlel("0% LEL");
                        }
                        res.setImei(imei);
                    }
                }
                resultList.add(res);
            }
        }
        PageUtil pageInfo = new PageUtil<>(page, pageSize, pages.getTotal(), resultList);
        return pageInfo;
    }

    @Override
    public Long create(WorkOrderCreateRequest params) {
        String spId;
        if (StringUtils.isEmpty(params.getSpId())) {
            spId = ApplicationUtils.getWorkingSpId();
        } else {
            spId = params.getSpId();
        }
        String orgCode = companyService.getOrgCode(spId,null);
        String woSeq = workOrderHistoryService.WORK_ORDER_NO_PREFIX + SnowflakeUtil.getSnowflakeId();

        Dtu dtu = equipmentService.getDeviceByImei(params.getImei(), spId);
        if (dtu == null) {
            throw new BizException("设备不存在！");
        }
        LatestLog latestLog = latestLogService.get(params.getImei(), spId);

        List<AsstOrderCreateRequest> list = new ArrayList<>();
        AsstOrderCreateRequest req = new AsstOrderCreateRequest();
        BeanUtils.copyProperties(params, req);
        req.setOutOrderCode(woSeq);
        req.setFromSystem(4);
        req.setOrgCode(orgCode);
        //发起的报警器设备
        List<String> query = service.getQueryParams();
        List<Map<String, String>> customerCode = service.dictMap(null, query, null);
        List<OrderDeviceRequest> orderDeviceList = new ArrayList<>();
        OrderDeviceRequest orderDeviceRequest = new OrderDeviceRequest();
        orderDeviceRequest.setDeviceName(dtu.getName());
        orderDeviceRequest.setEquipmentType(dtu.getEquipmentType());
        orderDeviceRequest.setIMEI(dtu.getIMEI());
        orderDeviceRequest.setDetectionType(service.setDetection(query, customerCode, dtu.getDetectionType()));
        if (latestLog != null) {
            orderDeviceRequest.setConcentration(latestLog.getConcentration());
            orderDeviceRequest.setMalfunctionReason(latestLog.getEquipmentStatusInfo());
        }
        orderDeviceList.add(orderDeviceRequest);
        req.setOrderDeviceList(orderDeviceList);
        //获取地址和经纬度
        if (StringUtils.isEmpty(dtu.getInstallationAddress()) || StringUtils.isEmpty(dtu.getPositionLon()) || StringUtils.isEmpty(dtu.getPositionLat())) {
            throw new BizException("安装地址为空，不能创建预约服务");
        } else {
            req.setAddress(dtu.getInstallationAddress());
            req.setLocation(dtu.getPositionLon() + "," + dtu.getPositionLat());
        }
        list.add(req);
        String body = httpUtil.getBody(JSONObject.toJSONString(list), workOrderUrl + AsstConstants.ORDER_CREATE_URL, null);
        JSONObject jsonObject = JSONObject.parseObject(body);
        if (jsonObject.get("code").equals(0)) {
            AsstWorkOrderResponse asstWorkOrder = JSONObject.toJavaObject((JSON) jsonObject.getJSONArray("data").get(0), AsstWorkOrderResponse.class);
            WorkOrderHistory history = new WorkOrderHistory();
            history.setWoSeq(woSeq);
            history.setDeviceId(params.getImei());
            history.setOrderNo(asstWorkOrder.getOrderNo());
            history.setWorkSystem(0);
            if (latestLog != null) {
                history.setConcentration(latestLog.getConcentration());
                history.setDeviceStatus(latestLog.getEquipmentStatus());
            }
            history.setReason(latestLog.getEquipmentStatusInfo());
            history.setSpId(spId);
            List<BizResponse> bizList = this.getBizList(spId);
            int status = 0;
            for (BizResponse bizResponse : bizList) {
                if (bizResponse.getBizCode().equals(params.getBizCode())) {
                    status = bizResponse.getTemplateType();
                    continue;
                }
            }
            history.setOrderType(status == 5 ? 3 : 2);
            history.setOperatorBy(ApplicationUtils.getWorkingUser().getName()+"("+ApplicationUtils.getWorkingUser().getUsername()+")");
            workOrderHistoryService.save(history);
            return history.getId();
        } else {
            throw new BizException(jsonObject.get("msg").toString());
        }
    }

    @Override
    public String createV2(OrderCreateRequest params) {
        String body = httpUtil.getBody(JSONObject.toJSONString(params), 
                workOrderUrl + AsstConstants.ORDER_CREATE_URL_V2, 
                params.getSpId());
        JSONObject jsonObject = JSONObject.parseObject(body);
        if (jsonObject.get("code").equals(0)) {
            return jsonObject.getString("data");
        } else {
            String msg = jsonObject.get("msg")!=null?jsonObject.getString("msg"):"创建工单失败";
            throw new BizException(msg);
        }
    }

    @Override
    public List<OrgInfoResponse> getDeptList(OrgInfoRequest params) {
        String body = httpUtil.getBody(JSONObject.toJSONString(params), 
                workOrderUrl + AsstConstants.ORDER_DEPT_URL_V2, 
                params.getSpId());
        JSONObject jsonObject = JSONObject.parseObject(body);
        if (jsonObject.get("code").equals(0)) {
            String data = jsonObject.getString("data");
            return JSONArray.parseArray(data, OrgInfoResponse.class);
        } else {
            String msg = jsonObject.get("msg")!=null?jsonObject.getString("msg"):"查询部门失败";
            throw new BizException(msg);
        }
    }

    @Override
    public Map getOrderCountByImei(List<String> imeiList, List<Integer> orderStatuses) {
        log.info("getOrderCountByImei start");
        Map map = new HashMap();
        LambdaQueryWrapper<WorkOrderHistory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WorkOrderHistory::getIsDeleted, 0).in(WorkOrderHistory::getDeviceId, imeiList);
        List<WorkOrderHistory> historyList = workOrderHistoryService.list(queryWrapper);
        if (!CollectionUtils.isEmpty(historyList)) {
            for (String imei : imeiList) {
                int count = 0;
                List<WorkOrderHistory> historyList1 = historyList.stream().filter(a -> a.getDeviceId().equals(imei)).collect(Collectors.toList());
                for (WorkOrderHistory history : historyList1) {
                    if (history.getHandleStatus().equals(0)) {
                        count = count + 1;
                    }
                }
                map.put(imei, count);
            }
        }
        log.info("getOrderCountByImei end:" + map.toString());
        return map;
    }

    @Override
    public List<ServicerSchedulingResponse> queryScheduleSurplusCount(String date, String lineBizCode, String bizCode,String spId) {
        if (StringUtils.isEmpty(spId)) {
            spId = ApplicationUtils.getWorkingSpId();
        }
        String url = workOrderUrl + AsstConstants.SCHEDULE_SURPLUS_COUNT_URL + "?lineBizCode=" + lineBizCode + "&bizCode=" + bizCode +
                "&date=" + date + "&spId=" + spId;

        String body = httpUtil.get(url, null);
        JSONObject jsonObject = JSONObject.parseObject(body);
        CommonResponse<List<ServicerSchedulingResponse>> res = JSONObject.toJavaObject(jsonObject, CommonResponse.class);
        return res.getData();
    }

    @Override
    public List<SchedulingSumCountResponse> getSurplusCountByDate(String lineBizCode, String bizCode, String startDate, String endDate,String spId) {
        if (StringUtils.isEmpty(spId)) {
            spId = ApplicationUtils.getWorkingSpId();
        }
        String url = workOrderUrl + AsstConstants.SURPLUS_COUNT_BY_DATE_RUL + "?lineBizCode=" + lineBizCode + "&bizCode=" + bizCode +
                "&startDate=" + startDate + "&endDate=" + endDate + "&spId=" + spId;
        String body = httpUtil.get(url, null);
        JSONObject jsonObject = JSONObject.parseObject(body);
        CommonResponse<List<SchedulingSumCountResponse>> res = JSONObject.toJavaObject(jsonObject, CommonResponse.class);
        return res.getData();
    }

    /**
     * 根据工单号和工单状态查询工单列表
     *
     * @param orderNos
     * @param orderStatuses
     */
    private List<AsstOrderListResponse> getOrderList(List<String> orderNos, List<Integer> orderStatuses, List<String> spIds) {
        log.info("getOrderList start");
        try {
            Map map = new HashMap();
            map.put("orderNos", orderNos);
            if (!CollectionUtils.isEmpty(orderStatuses)) {
                map.put("orderStatuses", orderStatuses);
            }
            map.put("page", 1);
            map.put("pageSize", 10000);
            map.put("spIds", spIds);
            String url = workOrderUrl + AsstConstants.ORDER_LIST_URL;
            String body = httpUtil.getBody(JSONObject.toJSONString(map), url, null);
            log.info("根据工单号和工单状态查询工单列表:" + body);
            JSONObject jsonObject = JSONObject.parseObject(body);
            if (jsonObject.get("code").equals(0)) {
                List<AsstOrderListResponse> res = JSON.parseArray(jsonObject.getString("data"), AsstOrderListResponse.class);
                return res;
            } else {
                log.error(jsonObject.get("msg").toString());
            }
        } catch (Exception e) {
            log.error("根据工单号和工单状态查询工单列表查询失败", e);
        }
        return new ArrayList<>();
    }

    @Override
    public void cancelOrderV2(OrderCancelDTO params) {
        try{
            String body = httpUtil.getBody(JSONObject.toJSONString(params),
                    workOrderUrl + AsstConstants.ORDER_CANCEL_URL_V2,
                    params.getSpId());
            JSONObject jsonObject = JSONObject.parseObject(body);
            if (null == jsonObject) {
                throw new BizException("取消工单未拿到返回结果");
            }else if( null==jsonObject.get("code") || !jsonObject.get("code").equals(0) ) {
                String msg = jsonObject.get("msg")!=null?jsonObject.getString("msg"):"取消工单失败";
                throw new BizException(msg);
            }
        }catch (Exception e){
            log.error("取消工单失败", e);
            throw new BizException(e.getMessage());
        }
    }

    @Override
    public Map<String, AsstOrderListResponse> getOrdersMap(List<String> orderNos,List<String> spIds) {
        List<AsstOrderListResponse> list = getOrderList(orderNos,null,spIds);
        Map<String, AsstOrderListResponse> result = list.stream()
                .collect(Collectors.toMap(AsstOrderListResponse::getOrderNo, Function.identity()));
        return result;
    }
}
